package com.zc58s.demo2.ribbitmq;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * 路由模式生产者
 *
 * @author : fujc-dev@qq.com
 * @created : 2022/8/20 16:27
 */

public class Producer03_routing {

    private static final String EXCHANGE_ROUTING_INFORM = "exchange_routing_inform";
    private static final String QUEUE_INFORM_EMAIL = "queue_inform_email";
    private static final String QUEUE_INFORM_SMS = "queue_inform_sms";
    private static final String ROUTING_KEY_EMAIL = "inform_email";
    private static final String ROUTING_KEY_SMS = "inform_sms";

    public static void main(String[] args) {
        //通过连接工厂创建新的连接
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("192.168.31.131");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("superAdmin!112233");
        // 设置虚拟机，一个MQ的服务可以设置多个虚拟机，每个虚拟机就相当于一个独立的MQ
        connectionFactory.setVirtualHost("/");
        // 生产者和MQ建立连接
        Connection connection;
        try {
            // 创建新连接
            connection = connectionFactory.newConnection();
            // 创建会话通道，生产者和MQ服务所有通信都在channel中完成
            Channel channel = connection.createChannel();
            // 声明队列，如果队列在mq中没有则要创建
            //参数：String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments
            /*
             * 参数明细：
             * 1、queue 队列名称
             * 2、durable 是否持久化，如果持久化，mq重启后队列还在
             * 3、exclusive 是否独占连接，队列只允许在该连接中访问，如果连接关闭队列自动删除，如果将此设置为true可用于临时队列的创建
             * 4、autoDelete 自动删除，队列不再使用时是否自动删除此队列，如果将此参数和exclusive参数设置为ture就可以实现临时队列
             * 5、arguments 参数，可以设置一个队列的扩展参数，比如：设置存活时间
             */
            channel.queueDeclare(QUEUE_INFORM_EMAIL, true, false, false, null);
            channel.queueDeclare(QUEUE_INFORM_SMS, true, false, false, null);
            //声明交换机
            //参数：String exchange, String type
            /**
             * 1、exchange 交换机名称
             * 2、type 交换机的类型
             * fanout：对应的rabbitmq的工作模式是publish/subscribe
             * direct：对应的Routing的工作模式
             * topic：对应的通配符的工作模式
             * headers：对应headers的工作模式
             */
            channel.exchangeDeclare(EXCHANGE_ROUTING_INFORM, BuiltinExchangeType.DIRECT);
            //进行交换机和队列进行绑定
            //参数：String queue, String exchange, String routingKey
            /**
             * 1、queue 队列名称
             * 2、exchange 交换机名称
             * 3、routingKey 路由Key，交换机会根据路由key的值来将消息转发到指定队列,在发布订阅模式中设置为空字符串
             */
            channel.queueBind(QUEUE_INFORM_EMAIL, EXCHANGE_ROUTING_INFORM, ROUTING_KEY_EMAIL);
            channel.queueBind(QUEUE_INFORM_SMS, EXCHANGE_ROUTING_INFORM, ROUTING_KEY_SMS);
            // 发送消息
            //参数：String exchange, String routingKey,  BasicProperties props, byte[] body
            /**
             * 参数明细：
             * 1、exchange  交换机。如果不指定，将使用mq默认交换机（设置为空字符串）
             * 2、routingKey 路由Key，交换机会根据路由key的值来将消息转发到指定队列,如果使用默认交换机，routingKey要设置为队列名称
             * 3、props 消息的属性
             * 4、body 消息体，消息内容
             */
            for (int i = 0; i < 5; i++) {
                String message = "send email inform message to user";
                channel.basicPublish(EXCHANGE_ROUTING_INFORM, ROUTING_KEY_EMAIL, null, message.getBytes());
                System.out.println("Send Message To MQ：" + message);
            }

            for (int i = 0; i < 5; i++) {
                String message = "send sms inform message to user";
                channel.basicPublish(EXCHANGE_ROUTING_INFORM, ROUTING_KEY_SMS, null, message.getBytes());
                System.out.println("Send Message To MQ：" + message);
            }

        } catch (IOException | TimeoutException e) {
            e.printStackTrace();
        } finally {

        }

    }
}
